Technical Q&A QA1340
Registering for sleep notifications

Q: How can my application get notified when the computer is going to sleep or waking from sleep?

A: The following code snippet shows how to install a sleep notification handler. Your application can use this notification to take action on system sleep and on system wakeup. You can also use the sleep callback to prevent idle sleep if you have something important going on, however, most applications should not disable idle sleep.

Listing 1: Installing a sleep notification handler.

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>

#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>

#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>

io_connect_t  root_port;

void
MySleepCallBack(void * x, io_service_t y, natural_t messageType, void * messageArgument)
{
    printf("messageType %08lx, arg %08lx\n",
      (long unsigned int)messageType, (long unsigned int)messageArgument);
    
    switch ( messageType ) {
        case kIOMessageSystemWillSleep:
            IOAllowPowerChange(root_port, (long)messageArgument);
            break;
        case kIOMessageCanSystemSleep:
            /* Idle sleep is about to kick in, but applications have a chance to prevent sleep
            by calling IOCancelPowerChange.  Most applications should not do this. */

            //IOCancelPowerChange(root_port, (long)messageArgument);

            /*  Power Manager waits for your reply via one of these functions for up
            to 30 seconds. If you don't acknowledge the power change by calling
            IOAllowPowerChange(), you'll delay sleep by 30 seconds. */

            IOAllowPowerChange(root_port, (long)messageArgument);
            break;
        case kIOMessageSystemHasPoweredOn:
            break;
    }
}


int
main(int argc, char **argv)
{
    IONotificationPortRef  notify;
    io_object_t            anIterator;

    root_port = IORegisterForSystemPower(0, &notify, MySleepCallBack, &anIterator);
    if ( root_port == NULL ) {
            printf("IORegisterForSystemPower failed\n");
            return 1;
    }

    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                        IONotificationPortGetRunLoopSource(notify),
                        kCFRunLoopCommonModes);
                        
    printf("waiting...\n\n");
    
    /* Start the run loop to receive sleep notifications.  You don't need to
    call this if you already have a Carbon or Cocoa EventLoop running. */
    CFRunLoopRun();
        
    return (0);
}

Document Revision History

DateNotes
2004-10-25First Version

Posted: 2004-10-25